package ma.cdm.compteRendu.dao;
// default package


import static org.hibernate.criterion.Example.create;

import java.util.ArrayList;
import java.util.List;

import ma.cdm.compteRendu.bo.MembreComite;
import ma.cdm.compteRendu.bo.PersonneRole;
import ma.cdm.compteRendu.bo.PersonneRoleId;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.transaction.annotation.Transactional;

/**
 	* A data access object (DAO) providing persistence and search support for MembreCOmite entities.
 			* Transaction control of the save(), update() and delete() operations 
		can directly support Spring container-managed transactions or they can be augmented	to handle user-managed Spring transactions. 
		Each of these methods provides additional information for how to configure it for the desired type of transaction control. 	
	 * @see .MembreCOmite
  * @author Limouri Anouar 
 */
    @Transactional   
public class MembreComiteDAO  {
	     private static final Logger log = LoggerFactory.getLogger(MembreComiteDAO.class);
		//property constants



    private SessionFactory sessionFactory;
    
   @Autowired
   private PersonneRoleDAO personneRoleDAO;
   
   @Autowired
   private ComiteDAO comiteDAO;
   
   @Autowired
   private RoleDAO roleDAO;
   
   
    public RoleDAO getRoleDAO() {
	return roleDAO;
}

public void setRoleDAO(RoleDAO roleDAO) {
	this.roleDAO = roleDAO;
}

	public PersonneRoleDAO getPersonneRoleDAO() {
		return personneRoleDAO;
	}
	
	public void setPersonneRoleDAO(PersonneRoleDAO personneRoleDAO) {
		this.personneRoleDAO = personneRoleDAO;
	}


	public ComiteDAO getComiteDAO() {
		return comiteDAO;
	}

	public void setComiteDAO(ComiteDAO comiteDAO) {
		this.comiteDAO = comiteDAO;
	}

	public void setSessionFactory(SessionFactory sessionFactory){
       this.sessionFactory = sessionFactory;
    }

    private Session getCurrentSession(){
     return sessionFactory.getCurrentSession(); 
    }
	protected void initDao() {
		//do nothing
	}
    
    public void save(MembreComite transientInstance) {
        log.debug("saving MembreComite instance");
        try {
            getCurrentSession().save(transientInstance);
            log.debug("save successful");
        } catch (RuntimeException re) {
            log.error("save failed", re);
            throw re;
        }
    }
    
	public void delete(MembreComite persistentInstance) {
        log.debug("deleting MembreComite instance");
        try {
            getCurrentSession().delete(persistentInstance);
            log.debug("delete successful");
        } catch (RuntimeException re) {
            log.error("delete failed", re);
            throw re;
        }
    }
    
    public MembreComite findById( java.lang.String id) {
        log.debug("getting MembreComite instance with id: " + id);
        try {
            MembreComite instance = (MembreComite) getCurrentSession()
                    .get(MembreComite.class, id);
            return instance;
        } catch (RuntimeException re) {
            log.error("get failed", re);
            throw re;
        }
    }
    
    
    public List<MembreComite> findByExample(MembreComite instance) {
        log.debug("finding MembreComite instance by example");
        try {
            List<MembreComite> results = (List<MembreComite>) getCurrentSession() .createCriteria("MembreComite").add( create(instance) ).list();
            log.debug("find by example successful, result size: " + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }
    
    public List<MembreComite>findMembrePresentRpport(long reportId)
    {
        try {
        	Criteria criteria = getCurrentSession().createCriteria(MembreComite.class);
        	criteria.createAlias("compteRendus","cr");
            criteria.add(Restrictions.eq("cr.idcompterendu", reportId));
            List results = criteria.list();
            return results;
        } catch (RuntimeException re) {
            log.error("find findMembrePresentRpport failed", re);
            throw re;
        }
    }
    
//    public void addMembrePresentCompteRendu(Long reportId  ,String membre)
//    {
//    	try {
//            String queryString = "insert into membrespresents	(IDCOMPTERENDU,MATRICULE) VALUES (?,?)";
//            Query queryObject = getCurrentSession().createSQLQuery(queryString);
//   		    queryObject.setLong(0, reportId);
//   		    queryObject.setString(1, membre);
//   		    queryObject.executeUpdate();
//         } catch (RuntimeException re) {
//            log.error("addMembrePresentCompteRendu failed", re);
//            throw re;
//         }
//    }
    
    public List<MembreComite>findMembreByComite(long comiteID)
    {
        log.debug("finding MembreCOmite instance by comite id");
        try {  
        	Criteria criteria = getCurrentSession().createCriteria(MembreComite.class);
        	criteria.createAlias("personneRoles","personneRole");
        	criteria.createAlias("personneRole.comite","comite");
            criteria.add(Restrictions.eq("comite.idcomite", comiteID));
            criteria.addOrder(Order.asc("ordre"));
            List results = criteria.list();
            log.debug("finding MembreComite instance by comite id successful, result size: " + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }
    
    public void addMembreToComite(String membreId,Long comiteId,Long roleId)
    {
    	if(membreId == null || StringUtils.isEmpty(membreId.trim()))
    	{
    		return;
    	}	
    	
    		MembreComite membr = findById(membreId);
 			if(membr == null)
 			{
 				membr = new MembreComite(membreId);
 			    save(membr); 	  			  
 			}			
 		    PersonneRoleId id = new PersonneRoleId();
 		    id.setIdcomite(comiteId);
 		    id.setIdrole(roleId);
 		    id.setMatricule(membreId);
 		    
 		   PersonneRole pr = new PersonneRole(id, membr, comiteDAO.findById(comiteId), roleDAO.findById(roleId));
 		   personneRoleDAO.save(pr);
		
    }
    
    public static void main(String args[])
   	{  	 
   	  	ApplicationContext clsCtx =
   		      new FileSystemXmlApplicationContext("C:\\Users\\cdm-u6688\\workspace\\GesCompteRendu\\src\\main\\webapp\\WEB-INF\\application-context.xml");
   	 MembreComiteDAO dao = MembreComiteDAO.getFromApplicationContext(clsCtx);
   	 RoleDAO rdao = RoleDAO.getFromApplicationContext(clsCtx);
   	 List<String> membres = new ArrayList<String>();
   	 membres.add("cdm-u6688");
   	 membres.add("cdm-u6068");
    membres.add("cdm-u3964");
   	membres.add("cdm-u5218");
   	dao.addMembreToComite("cdm-u6688",2L, 2L);
//   	dao.addMembreToComite("cdm-u6068", 1L, 2L);
//   	dao.addMembreToComite("cdm-u3964", 1L, 3L);
//   	dao.addMembreToComite("cdm-u5218", 1L, 4L);

//dao.deleteMembresFromComite(membres, 2L);
//	   	List<MembreComite> members = dao.findMembreByComite(1L);
//	   	for (MembreComite membreComite : members) {
//	   		System.out.println(membreComite.getMatricule());	
//	   		Role r =rdao.getPersonneComiteRole(membreComite.getMatricule(), 2L);
//	   		if(r != null)
//	   		System.out.println(r.getLibellerole());
//		}
   	}
    
    
    
    @SuppressWarnings({ "unchecked" })
	public void deleteMembresFromComite(List<String> membreIds,Long comiteId)
    {
    	if(membreIds == null || membreIds.size() == 0)
    	{
    		return;
    	}
	
		Criteria criteria = getCurrentSession().createCriteria(PersonneRole.class);
		criteria.add(Restrictions.eq("id.idcomite", comiteId));
		criteria.add(Restrictions.in("id.matricule", membreIds.toArray(new String[0])));
		List<PersonneRole> results = criteria.list();
	
    	for (PersonneRole personneRole : results) {
			personneRoleDAO.delete(personneRole);
		}
		
    }

    public List findByProperty(String propertyName, Object value) {
      log.debug("finding MembreComite instance with property: " + propertyName
            + ", value: " + value);
      try {
         String queryString = "from MembreComite as model where model." 
         						+ propertyName + "= ?";
         Query queryObject = getCurrentSession().createQuery(queryString);
		 queryObject.setParameter(0, value);
		 return queryObject.list();
      } catch (RuntimeException re) {
         log.error("find by property name failed", re);
         throw re;
      }
	}


	public List findAll() {
		log.debug("finding all MembreComite instances");
		try {
			String queryString = "from MembreComite";
	         Query queryObject = getCurrentSession().createQuery(queryString);
			 return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}
	
    public MembreComite merge(MembreComite detachedInstance) {
        log.debug("merging MembreComite instance");
        try {
            MembreComite result = (MembreComite) getCurrentSession()
                    .merge(detachedInstance);
            log.debug("merge successful");
            return result;
        } catch (RuntimeException re) {
            log.error("merge failed", re);
            throw re;
        }
    }

    public void attachDirty(MembreComite instance) {
        log.debug("attaching dirty MembreComite instance");
        try {
            getCurrentSession().saveOrUpdate(instance);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }
    
    public void attachClean(MembreComite instance) {
        log.debug("attaching clean MembreComite instance");
        try {
                      	getCurrentSession().buildLockRequest(LockOptions.NONE).lock(instance);
          	            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

	public static MembreComiteDAO getFromApplicationContext(ApplicationContext ctx) {
    	return (MembreComiteDAO) ctx.getBean("membreComiteDAO");
	}
}